大家好,我是 Yubin
本篇文章會介紹什麼是 Keycloak,一步一步在本地端把 Keycloak 伺服器打起來,並使用 fastify-keycloak-adapter
讓我們的前後端整合的網頁應用程式整合 Keycloak 登入。
我們現在有一個前後端整合的 Fastify 專案,但因為沒有實作登入等認證機制,所以任何人都可以瀏覽我們的頁面,戳我們的 API。
但我想讓我的網站,只有我的會員可以瀏覽,只有我的會員可以跟我拿取資源。
那你需要實作一個使用者資料庫、認證機制、登入畫面、登出功能以及使用者的 Session 管理系統 (總不能讓使用者登入一次就一輩子不用再登入)。
聽起來很麻煩,事實上真的很麻煩,而且一個設計不好可能造成嚴重的資安危害,所以我們需要一個專業的解決方案,這裡我們使用 Keycloak。
Keycloak 是 Red Hat 公司在 JBoss 社群維護的一個開源專案。
是一個使用者身份及 Session 管理的解決方案。
GitHub 專案在這裡 https://github.com/keycloak/keycloak 。
會使用 Keycloak 作為登入伺服器有幾個特點
還有一個點是,可以快速的在本地端設定使用者資料庫,方便程式的開發。
我們現在要先把一個 Keycloak Server 在本機起起來,可以去 Keycloak 官網下載最新版本的 Server 執行檔,或是更快速的,使用 Container。
打開 terminal 敲入:
docker run -d -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak
使用的 image 是 jboss/keycloak
。
-p 8080:8080
這個 image 預設會把服務開在 8080 port,我們用本機的 8080 去 mapping 他-e KEYCLOAK_USER=admin
設定 Keycloak Server 的管理員登入帳號-e KEYCLOAK_PASSWORD=admin
設定 Keycloak Server 的管理員登入密碼
等 container 啟動好,就可以打開瀏覽器,網址列輸入 localhost:8080
。
就可以看到 Keycloak Server 的預設頁面,接著點擊 Administration Console
進入管理頁面。
進入管理頁面前,會跳轉到 Keycloak 登入畫面。
在啟動 Container 的時候我有帶 KEYCLOAK_USER
跟 KEYCLOAK_PASSWORD
的環境變數,所以我知道管理者帳號密碼都是 admin/admin
。
這邊要注意,預設情況下沒有管理者帳號是無法登入管理頁面的。
登入之後可以看到如下畫面。
Realm 在 Keycloak 裡面可以想成 namespace 的意思,每個 Realm 記錄著不同的使用者,Realm 之間彼此是獨立的。
預設會有一個 master
的 Realm。
我們點擊 Add realm
新增一個 Realm: demo
。
按下 Create
之後就建立好我們的 realm。
左側點擊 Users
進入使用者的頁面。
User 表示人,某個人要操作系統,以 OAuth2.0 的術語來說是就是資源擁有者。
預設狀態下,User 會需要透過輸入帳號密碼的方式進行登入,我們先來建立這個 demo realm 底下的使用者。
點擊 Add user
後,填入要新增的使用者。
這邊新增使用者 user01
,除了 username 其他欄位都可以留空。
接著點擊 Credentials
頁簽,來設定這個使用者的密碼。
這邊方便測試,弄個好記的。
Temporary
選項如果勾選,表示使用者第一次登入後要自行改密碼,預設是勾選狀態。
這邊只是想測試,所以把它關掉。
接著按 Save Passowrd
儲存。
建立好使用者後,我們來設定哪些服務可以來使用我們 Keycloak。
Keycloak 裡面的 Client,可以想成來使用 Keycloak 的服務。
不是每個網站都可以使用我這個 Keycloak 服務,而是要透過特定的 Client,Client 上會有紀錄一些識別用的資訊,經過認證才能使用。
例如,我要登入 A 網站,A 網站帶著某個 Client 的資訊,把我導向 Keycloak 的登入畫面,我登入成功後 Keycloak 把我導回 A 網站。
這邊的 Client 是要事先被建立的,而且上頭要表明 A 網站是合法 (Valid) 的網站,A 網站才能使用這座 Keycloak Server 提供的服務。
我們來新增一個 Client,左側點擊 Clients
進入 Client 頁面,再點擊 Create
。
輸入 Client ID,這邊使用 client01
。
接著我們把 Access Type 設定為 Confidential
,要使用 client secret 來初始化登入協議。
Access Type 的解釋 (從網站說明複製的)
Confidential
clients require a secret to initiate login protocol.Public
clients do not require a secret.Bearer-only
clients are web services that never initiate a login.
如前面提到的,不是每個網站都可以使用這座 Keycloak Server 的服務,必須登記在這裡。
目前只是在本機開發測試,所以填入 http://localhost:8888/*
,如果是部屬出去的服務,就要填寫該服務的 Domain Name。
接著按 Save
儲存。
接著點擊 Credentials
頁籤,可以看到我們這個 Client 專屬的 Secret。
把 Secret 複製起來備用。
Keycloak Server 的設定到此告一段落,我們建立了一個 Realm 叫做 demo
,建立了一個 Client 叫做 client01
,也在這個 Realm 底下建立了一個使用者 user01
。
容易搞混的是,User 是跟著 Realm,不是跟著 Client。
一個 Realm 可以有多個 User 與多個 Client,跟其他 Realm 彼此獨立。
現在 Keycloak Server 準備好了,我們要讓我們的程式可以支援 Keycloak。
手上沒有 Fastify 前後端整合專案的朋友,可以參考這篇 Fastify101: 前後端整合 React and Fastify-Static ,跟著文章步驟產生,或參考文章最底下的範例專案。
fastify-keycloak-adapter 是一個 Fastify Plugin,可以快速的介接 Keycloak 的服務。
如果使用者沒有認證資訊或認證資訊過期,會讓使用者跳轉到 Keycloak 登入頁面。使用者登入完會再跳轉回我們的網站,跳轉回來後就可以拿到使用者的身份資訊。
透過 npm 安裝:
npm i fastify-keycloak-adapter
透過 server.register()
進行註冊,並帶入 KeycloakOptions。
import fastify, { FastifyInstance } from 'fastify'
import keycloak, { KeycloakOptions } from 'fastify-keycloak-adapter'
const server: FastifyInstance = fastify()
const opts: KeycloakOptions = {
appOrigin: 'http://localhost:8888',
keycloakSubdomain: 'localhost:8080/auth/realms/demo',
clientId: 'client01',
clientSecret: 'O9uEfbDHxXgpqET7RVzWnXHE6ecSlR7F'
}
server.register(keycloak, opts)
appOrigin
輸入你的網站首頁的 url,記得必須登記在 Client 的 Valid Redirect URLs
清單中。keycloakSubdomain
要連的那座 Keycloak Server 及使用 realm 的位址,localhost:8080
是 Keycloak Server 的 domain,demo
是我們要使用的 Realm。clientId
,要使用 Client 的 Client ID。clientSecret
,要使用 Client 的 Client Secret。(請從自己的管理頁面複製,你的不會跟我一樣)更多 KeycloakOptions 的可用選項,請參考官方 GitHub 文件。
設定好上述資訊後,我們的 App 就整合好 Keycloak 的服務了!
接著把前端專案 build 好,後端專案 build 好起起來。
打開瀏覽器,網址輸入 localhost:8888
。
原本可以直接瀏覽到前端畫面,現在被跳轉到 Keycloak 的登入頁面。
輸入剛剛我們建立的 user01 的帳號密碼。
登入成功後,會跳轉回我們的網站。
到這裡就完成 Fastify 前後端整合專案介接 Keycloak 的服務。
本篇文章介紹了 Keycloak 是什麼,以及 Step by Step 的帶大家走過 Keycloak 測試伺服器的架設與設定。
再利用 fastify-keycloak-adapter 這個 Plugin 快速的讓 Fastify App 可以介接 Keycloak 的服務。
更多 Plugin 的使用,像是怎麼在程式中拿到使用者的資訊、如何讓使用者登出,等等,可以參考官方的文件。
這個 Plugin 目前是我在維護,有任何問題或建議都可以直接丟 issue 或丟 PR 給我 XD
以上完整的專案範例可以參考 GitHub。
篇幅有點長,感謝收看。